package com.mc.fastkit.dialog.animator

import android.animation.AnimatorSet
import android.animation.IntEvaluator
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.view.View
import androidx.core.animation.doOnEnd
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import kotlin.math.max

/**
 * contentView默认动画，由不同的[AnimatorItem]组合而成
 * @author: MasterChan
 * @date: 2023-12-29 15:11
 */
open class ContentAnimator(private val scaleFactor: Float = 0.85f) : AbsDialogAnimator() {

    private val intEvaluator by lazy { IntEvaluator() }
    val animatorItems = mutableListOf<AnimatorItem>()
    private var initTranslateX = 0f
    private var initTranslateY = 0f
    private var targetTranslateX = 0f
    private var targetTranslateY = 0f
    private var initPivotX = 0f
    private var initPivotY = 0f
    private var targetPivotX = 0f
    private var targetPivotY = 0f
    private var startScrollX = 0
    private var startScrollY = 0

    override fun init() {
        initTranslateX = target!!.translationX
        initTranslateY = target!!.translationY
        targetTranslateX = initTranslateX
        targetTranslateY = initTranslateY

        initPivotX = target!!.pivotX
        initPivotY = target!!.pivotY
        targetPivotX = initPivotX
        targetPivotY = initPivotY
    }

    override fun show(onEnd: (() -> Unit)?) {
        val set = AnimatorSet()
        setTargetPivot()
        animatorItems.forEach {
            when (it) {
                AnimatorItem.Alpha -> {
                    set.playTogether(
                        ObjectAnimator.ofFloat(target!!, View.ALPHA, target!!.alpha, 1f)
                    )
                }

                is AnimatorItem.Translate -> {
                    target!!.translationX = targetTranslateX
                    target!!.translationY = targetTranslateY
                    set.playTogether(
                        ObjectAnimator.ofFloat(
                            target!!, View.TRANSLATION_X, target!!.translationX, initTranslateX
                        )
                    )
                    set.playTogether(
                        ObjectAnimator.ofFloat(
                            target!!, View.TRANSLATION_Y, target!!.translationY, initTranslateY
                        )
                    )
                }

                is AnimatorItem.Scale -> {
                    target!!.pivotX = targetPivotX
                    target!!.pivotY = targetPivotY
                    target!!.scaleX = scaleFactor
                    target!!.scaleY = scaleFactor
                    set.playTogether(
                        ObjectAnimator.ofFloat(target!!, View.SCALE_X, target!!.scaleX, 1f)
                    )
                    set.playTogether(
                        ObjectAnimator.ofFloat(target!!, View.SCALE_Y, target!!.scaleY, 1f)
                    )
                }

                is AnimatorItem.Scroll -> {
                    target!!.pivotX = targetPivotX
                    target!!.pivotY = targetPivotY
                    set.playTogether(ValueAnimator.ofInt(max(startScrollX, startScrollY), 0).apply {
                        addUpdateListener { animation ->
                            target!!.scrollTo(
                                intEvaluator.evaluate(animation.animatedFraction, startScrollX, 0),
                                intEvaluator.evaluate(animation.animatedFraction, startScrollY, 0)
                            )
                        }
                    })
                }
            }
        }
        set.interpolator = FastOutSlowInInterpolator()
        set.duration = duration
        set.doOnEnd { onEnd?.invoke() }
        set.start()
    }

    private fun setTargetPivot() {
        animatorItems.forEach {
            when (it) {
                AnimatorItem.Alpha -> target!!.alpha = 0f
                AnimatorItem.Translate.Left -> targetTranslateX = -target!!.width.toFloat()
                AnimatorItem.Translate.Top -> targetTranslateY = -target!!.measuredHeight.toFloat()
                AnimatorItem.Translate.Right -> targetTranslateX = target!!.measuredWidth.toFloat()
                AnimatorItem.Translate.Bottom -> targetTranslateY = target!!.measuredHeight.toFloat()

                AnimatorItem.Scale.Center -> {
                    targetPivotX = target!!.measuredWidth / 2f
                    targetPivotY = target!!.measuredHeight / 2f
                }

                AnimatorItem.Scale.TopLeft -> {
                    targetPivotX = 0f
                    targetPivotY = 0f
                }

                AnimatorItem.Scale.TopCenter -> {
                    targetPivotX = target!!.measuredWidth / 2f
                    targetPivotY = 0f
                }

                AnimatorItem.Scale.TopRight -> {
                    targetPivotX = target!!.measuredWidth.toFloat()
                    targetPivotY = 0f
                }

                AnimatorItem.Scale.BottomLeft -> {
                    targetPivotX = 0f
                    targetPivotY = target!!.measuredHeight.toFloat()
                }

                AnimatorItem.Scale.BottomCenter -> {
                    targetPivotX = target!!.measuredWidth / 2f
                    targetPivotY = target!!.measuredHeight.toFloat()
                }

                AnimatorItem.Scale.BottomRight -> {
                    targetPivotX = target!!.measuredWidth.toFloat()
                    targetPivotY = target!!.measuredHeight.toFloat()
                }

                AnimatorItem.Scale.LeftCenter -> {
                    targetPivotX = 0f
                    targetPivotY = target!!.measuredHeight.toFloat() / 2f
                }

                AnimatorItem.Scale.RightCenter -> {
                    targetPivotX = target!!.measuredWidth.toFloat()
                    targetPivotY = target!!.measuredHeight.toFloat() / 2f
                }

                AnimatorItem.Scroll.Top -> {
                    targetPivotX = target!!.measuredWidth / 2f
                    targetPivotY = 0f
                    startScrollX = 0
                    startScrollY = target!!.measuredHeight
                }

                AnimatorItem.Scroll.Bottom -> {
                    targetPivotX = target!!.measuredWidth / 2f
                    targetPivotY = target!!.measuredHeight.toFloat()
                    startScrollX = 0
                    startScrollY = -target!!.measuredHeight
                }

                AnimatorItem.Scroll.BottomLeft -> {
                    targetPivotX = 0f
                    targetPivotY = target!!.measuredHeight.toFloat()
                    startScrollX = target!!.measuredWidth
                    startScrollY = -target!!.measuredHeight
                }

                AnimatorItem.Scroll.BottomRight -> {
                    targetPivotX = target!!.measuredWidth.toFloat()
                    targetPivotY = target!!.measuredHeight.toFloat()
                    startScrollX = -target!!.measuredWidth
                    startScrollY = -target!!.measuredHeight
                }

                AnimatorItem.Scroll.Left -> {
                    targetPivotX = 0f
                    targetPivotY = target!!.measuredHeight.toFloat() / 2f
                    startScrollX = target!!.measuredWidth
                    startScrollY = 0
                }

                AnimatorItem.Scroll.Right -> {
                    targetPivotX = target!!.measuredWidth.toFloat()
                    targetPivotY = target!!.measuredHeight / 2f
                    startScrollX = -target!!.measuredWidth
                    startScrollY = 0
                }

                AnimatorItem.Scroll.TopLeft -> {
                    targetPivotX = 0f
                    targetPivotY = 0f
                    startScrollX = target!!.measuredWidth
                    startScrollY = target!!.measuredHeight
                }

                AnimatorItem.Scroll.TopRight -> {
                    targetPivotX = target!!.measuredWidth.toFloat()
                    targetPivotY = 0f
                    startScrollX = -target!!.measuredWidth
                    startScrollY = target!!.measuredHeight
                }
            }
        }
    }

    override fun dismiss(onEnd: (() -> Unit)?) {
        val set = AnimatorSet()
        setTargetPivot()
        animatorItems.forEach {
            when (it) {
                AnimatorItem.Alpha -> {
                    set.playTogether(
                        ObjectAnimator.ofFloat(target!!, View.ALPHA, target!!.alpha, 0f)
                    )
                }

                is AnimatorItem.Translate -> {
                    set.playTogether(
                        ObjectAnimator.ofFloat(
                            target!!, View.TRANSLATION_X, target!!.translationX, targetTranslateX
                        )
                    )
                    set.playTogether(
                        ObjectAnimator.ofFloat(
                            target!!, View.TRANSLATION_Y, target!!.translationY, targetTranslateY
                        )
                    )
                }

                is AnimatorItem.Scale -> {
                    set.playTogether(
                        ObjectAnimator.ofFloat(
                            target!!, View.SCALE_X, target!!.scaleX, scaleFactor
                        )
                    )
                    set.playTogether(
                        ObjectAnimator.ofFloat(
                            target!!, View.SCALE_Y, target!!.scaleY, scaleFactor
                        )
                    )
                }

                is AnimatorItem.Scroll -> {
                    set.playTogether(ValueAnimator.ofInt(max(startScrollX, startScrollY), 0).apply {
                        addUpdateListener { animation ->
                            target!!.scrollTo(
                                intEvaluator.evaluate(animation.animatedFraction, 0, startScrollX),
                                intEvaluator.evaluate(animation.animatedFraction, 0, startScrollY)
                            )
                        }
                    })
                }
            }
        }
        set.interpolator = FastOutSlowInInterpolator()
        set.duration = duration
        set.doOnEnd {
            target!!.scaleX = 1f
            target!!.scaleY = 1f
            target!!.pivotX = initPivotX
            target!!.pivotY = initPivotY
            target!!.translationX = initTranslateX
            target!!.translationY = initTranslateY
            target!!.scrollX = 0
            target!!.scrollY = 0
            onEnd?.invoke()
        }
        set.start()
    }

    fun clearAnimatorItems() {
        animatorItems.clear()
    }

    fun addAnimatorItem(item: AnimatorItem) {
        animatorItems.add(item)
    }

    fun setAnimatorItems(items: List<AnimatorItem>) {
        animatorItems.clear()
        animatorItems.addAll(items)
    }
}